﻿using System;
using System.Collections.Generic;

namespace DataAccessLayer
{
    /// <summary>
    /// The operation.
    /// </summary>
    internal delegate object operation(string type, Dictionary<string, object> args);

    /// <summary>
    /// The DAL interface.
    /// </summary>
    public static class DAL
    {
        private static Dictionary<string, DalEntity> _types; 

        /// <summary>
        /// Operation - Function matching.
        /// </summary>
        private static Dictionary<string, operation> dictionary;

        /// <summary>
        /// Initializes static members of the <see cref="DAL"/> class.
        /// </summary>
        static DAL()
        {
            dictionary = new Dictionary<string, operation>();
            dictionary.Add("Read", ReadAll);
            dictionary.Add("ReadById", ReadById);
            dictionary.Add("Create", Create);
            dictionary.Add("Write", Write);
            dictionary.Add("Remove", Remove);

            _types = new Dictionary<string, DalEntity>();
            _types.Add("Car", new Car());
            _types.Add("CarState", new CarState());
            _types.Add("Park", new Park());
            _types.Add("Driver", new Driver());
            _types.Add("ParkPoint", new ParkPoint());
            _types.Add("User", new User());
            _types.Add("PtivilegeLevel", new PrivilegeLevel());
        }

        /// <summary>
        /// Read all entities from DB.
        /// </summary>
        private static Reader ReadAll(string type, Dictionary<string, object> args)
        {
            ValidateType(type);
            return _types[type].ReadAll(args);
        }

        /// <summary>
        /// Read entity from DB by id.
        /// </summary>
        private static Dictionary<string, object> ReadById(string type, Dictionary<string, object> args)
        {
            ValidateType(type);
            return _types[type].ReadById(args);
        }

        /// <summary>
        /// Create an entity in DB.
        /// </summary>
        private static object Create(string type, Dictionary<string, object> args)
        {
            ValidateType(type);
            return _types[type].Create();
        }

        /// <summary>
        /// Write an entity in DB.
        /// </summary>
        private static object Write(string type, Dictionary<string, object> args)
        {
            ValidateType(type);
            return _types[type].Write(args);
        }

        /// <summary>
        /// Remove an entity from DB.
        /// </summary>
        private static object Remove(string type, Dictionary<string, object> args)
        {
            ValidateType(type);
            return _types[type].Remove(args);
        }

        /// <summary>
        /// The operation.
        /// </summary>
        /// <exception cref="ArgumentException">
        /// </exception>
        public static object Operation(string operation, string type, Dictionary<string, object> args)
        {

            if (dictionary.ContainsKey(operation))
            {
                return dictionary[operation](type, args);
            }
            else
            {
                throw new ArgumentException("Operation \"" + operation +"\" not found");
            }
        }

        /// <summary>
        /// Validate type.
        /// </summary>
        /// <exception cref="ArgumentException">
        /// </exception>
        private static void ValidateType(string type)
        {
            if(!_types.ContainsKey(type))
                throw new ArgumentException("Can't find the type \"" + type + '\"');
        }
    }
}
